import asyncio
import time,json
import threading
import zlib
from .func import *

class UdpReciver(threading.Thread):
    def __init__(self,remote_addr,queue,auth_str=''):
        threading.Thread.__init__(self)
        self.auth_str = auth_str
        self.transport = None
        self.remote_addr = remote_addr
        self.queue = queue
        self.running = False

    def run(self):
        if self.running:
            raise 'aready running'
        loop = asyncio.new_event_loop()
        def f():
            self.send_auth()
            loop.call_later(30, f)
        loop.call_later(10, f)
        connect = loop.create_datagram_endpoint(
            lambda: self,
            remote_addr=self.remote_addr)
        transport, protocol = loop.run_until_complete(connect)
        loop.run_forever()

    def send_auth(self):
        if not self.running:
            return
        self.send_ctr('o:'+self.auth_str)
        
    def send_ctr(self,message):
        header = bytearray(1);
        header[0] = 0x08
        payload = bytearray(message,'utf8');
        self.transport.sendto(header+payload)

    def connection_made(self, transport):
        self.transport = transport
        self.running = True;
        self.send_auth();
    def handle_ctr(self,bytes):
        pass

    def _decodeMessage(self,buf):
        compress_flag = buf[0] & 0x60
        if compress_flag == 0:
            payload = buf[1:]
        elif compress_flag == 0x20:
            payload = zlib.decompress(buf[1:]);
        else:
            raise 'unsupport compress'
        type_flag = buf[0] & 0x18
        if type_flag == 0x0:
            return payload;
        elif type_flag == 0x08:
            return payload.decode('utf8');
        elif type_flag == 0x10:
            json = payload.decode('utf8');
            return json.loads(json);
        else:
            raise 'unsupport data type'

    def datagram_received(self, data, addr):
        if data[0] & 0x80 == 0:
            return self.handle_ctr(data[1:])
        msg = self._decodeMessage(data);
        self.queue.put(msg)

    def error_received(self, exc):
        print('Error received:', exc)

    def connection_lost(self, exc):
        print("Socket closed, stop the event loop")